﻿#include "pch.h"
#include "InputBox.h"
#include "MainWindow.h"
#include "Resource.h"

BEGIN_MESSAGE_MAP(MainWindow, CDialog)
    ON_COMMAND(IDC_MENU_ITEM_DEFEAT, OnMenuItemDefeatClicked)
    ON_COMMAND(IDC_MENU_ITEM_FIND_RIVAL, OnMenuItemFindUsersClicked)
    ON_COMMAND(IDC_MENU_ITEM_RESTART, OnMenuItemRestartClicked)
    ON_MESSAGE(Const::UM_GAME_OVER, OnGameOver)
    ON_MESSAGE(Const::UM_GAME_START, OnGameStart)
    ON_MESSAGE(Const::UM_GET_FIND_USERS_RESULT, OnGetFindUsersResult)
    ON_MESSAGE(Const::UM_GET_INVITE_REQUEST, OnGetInviteRequest)
    ON_MESSAGE(Const::UM_GET_INVITE_RESULT, OnGetInviteResult)
    ON_MESSAGE(Const::UM_GET_LOGON_RESULT, OnGetLogonResult)
    ON_MESSAGE(Const::UM_GET_RIVAL_NAME, OnGetRivalName)
    ON_MESSAGE(Const::UM_RIVAL_QUIT_GAME, OnRivalQuitGame)
    ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

/**
 * 构造方法。
 * @param parent    父窗口
 */
MainWindow::MainWindow(CWnd* parent) :
    CDialog(IDD_MAIN_WINDOW, parent),
    mGame(NULL),
    mGameBoard(Const::GAME_BOARD_WIDTH, Const::GAME_BOARD_HEIGHT),
    mRivalWindow(this) {
}

/**
 * 析构方法。
 */
MainWindow::~MainWindow() {
    delete mGame;
}

/**
 * 登录。
 */
void MainWindow::Logon() {
    CString text;
    text.LoadString(NULL, IDS_INPUT_USERNAME);
    InputBox inputBox(this, text);
    if (inputBox.DoModal() == IDOK) {
        mGame->Logon(inputBox.GetStringValue());
    } else {
        delete mGame;
        exit(0);
    }
}

/**
 * 游戏结束事件的响应方法。
 * @param wParam    结束原因
 * @return 总是零
 */
LRESULT MainWindow::OnGameOver(WPARAM wParam, LPARAM) {
    // 设置菜单项
    CMenu* menu = CDialog::GetMenu();
    menu->EnableMenuItem(IDC_MENU_ITEM_FIND_RIVAL, MF_ENABLED);
    menu->EnableMenuItem(IDC_MENU_ITEM_DEFEAT, MF_GRAYED);
    menu->EnableMenuItem(IDC_MENU_ITEM_RESTART, MF_ENABLED);

    // 显示提示信息
    GameOverReason reason = (GameOverReason)wParam;
    switch (reason) {
        case LOST:
            AfxMessageBox(IDS_LOST, MB_ICONINFORMATION);
            break;
        case RIVAL_ADMIT:
            AfxMessageBox(IDS_RIVAL_ADMIT, MB_ICONINFORMATION);
            break;
        case SELF_ADMIT:
            AfxMessageBox(IDS_SELF_ADMIT, MB_ICONINFORMATION);
            break;
        case WON:
            AfxMessageBox(IDS_WON, MB_ICONINFORMATION);
            break;
    }

    return 0;
}

/**
 * 游戏开始事件的响应方法。
 * @param wParam    对手的名字
 * @return 总是零
 */
LRESULT MainWindow::OnGameStart(WPARAM wParam, LPARAM) {
    // 隐藏对手列表窗口
    mRivalWindow.ShowWindow(SW_HIDE);

    // 设置菜单项
    CMenu* menu = CDialog::GetMenu();
    menu->EnableMenuItem(IDC_MENU_ITEM_FIND_RIVAL, MF_GRAYED);
    menu->EnableMenuItem(IDC_MENU_ITEM_DEFEAT, MF_ENABLED);
    menu->EnableMenuItem(IDC_MENU_ITEM_RESTART, MF_GRAYED);

    // 显示对手的名字
    CString text;
    text.LoadString(IDS_CURRENT_RIVAL);
    text += (LPCTSTR)wParam;
    mStatusBar.SetText(text, 0, 0);

    return 0;
}

/**
 * 得到寻找用户结果事件的响应方法。
 * @param wParam    结果
 * @return 总是零
 */
LRESULT MainWindow::OnGetFindUsersResult(WPARAM wParam, LPARAM) {
    FindUsersResult* result = (FindUsersResult*)wParam;
    if (result->mUsernameList[0][0] != '\0') {
        mRivalWindow.SetUsernameList(result->mUsernameList);
        mRivalWindow.ShowWindow(SW_SHOW);
    }

    return 0;
}

/**
 * 得到挑战请求事件的响应方法。
 * @param wParam    对手的名字
 * @return 总是零
 */
LRESULT MainWindow::OnGetInviteRequest(WPARAM wParam, LPARAM) {
    LPCTSTR rivalName = (LPCTSTR)wParam;
    CString question(rivalName);
    CString tempString;
    tempString.LoadString(IDS_INVITE);
    question += tempString;
    BOOL accept = AfxMessageBox(question, MB_ICONQUESTION | MB_YESNO) == IDYES;
    mGame->AcceptInvite(rivalName, accept);

    return 0;
}

/**
 * 得到挑战结果事件的响应方法。
 * @param wParam    对手的名字
 * @param lParam    接受挑战则为 TRUE，否则为 FALSE
 * @return 总是零
 */
LRESULT MainWindow::OnGetInviteResult(WPARAM wParam, LPARAM lParam) {
    LPCTSTR rivalName = (LPCTSTR)wParam;
    CString information(rivalName);
    CString tempString;
    BOOL accept = (BOOL)lParam;

    if (accept) {
        tempString.LoadString(IDS_ACCEPT);
    } else {
        tempString.LoadString(IDS_REFUSE);
    }
    information += tempString;
    AfxMessageBox(information, MB_ICONINFORMATION);

    return 0;
}

/**
 * 得到登录结果事件的响应方法。
 * @param wParam    登录结果
 * @return 总是零
 */
LRESULT MainWindow::OnGetLogonResult(WPARAM wParam, LPARAM) {
    BOOL succeeded = (BOOL)wParam;
    if (succeeded) {
        AfxMessageBox(IDS_LOGON_SUCCEEDED, MB_ICONINFORMATION);
    } else {
        AfxMessageBox(IDS_LOGON_FAILED, MB_ICONINFORMATION);
        this->Logon();
    }

    return 0;
}

/**
 * 获取对手的名字事件的响应方法。
 * @param wParam    对手的名字
 * @return 总是零
 */
LRESULT MainWindow::OnGetRivalName(WPARAM wParam, LPARAM) {
    LPCTSTR rivalName = (LPCTSTR)wParam;
    mGame->Invite(rivalName);

    return 0;
}

/**
 * 初始化事件的响应方法。
 * @return 总是 TRUE
 */
BOOL MainWindow::OnInitDialog() {
    // 初始化
    CDialog::OnInitDialog();

    // 设置状态栏
    CRect rect;
    mStatusBar.Create(WS_CHILD | WS_VISIBLE | CCS_BOTTOM, rect, this, AFX_IDW_STATUS_BAR);
    CDialog::GetWindowRect(rect);
    int parts[] = { rect.Width() };
    mStatusBar.SetParts(1, parts);
    CString text;
    text.LoadString(IDS_CURRENT_RIVAL);
    mStatusBar.SetText(text, 0, 0);

    // 创建对手列表窗口
    mRivalWindow.Create(IDD_RIVAL_WINDOW, this);

    // 创建游戏区域
    CRect gameBoardRect(0, 0, Const::GAME_BOARD_WIDTH, Const::GAME_BOARD_HEIGHT);
    mGameBoard.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, gameBoardRect, this, 0);

    // 创建游戏
    try {
        mGame = new Game(this, mGameBoard.GetDrawer(), &mGameBoard);
    } catch (int) {
        AfxMessageBox(IDS_NETWORK_ERROR, MB_ICONERROR);
        exit(0);
    }

    // 登录
    this->Logon();

    return TRUE;
}

/**
 * 单击游戏区域事件的响应方法。
 * @param point 鼠标位置
 */
void MainWindow::OnLButtonUp(UINT, CPoint point) {
    mGame->OnGameBoardClicked(point.x, point.y);
}

/**
 * "认输"菜单项的单击响应方法。
 */
void MainWindow::OnMenuItemDefeatClicked() {
    mGame->Defeat();
}

/**
 * "寻找其它用户"菜单项的单击响应方法。
 */
void MainWindow::OnMenuItemFindUsersClicked() {
    mGame->FindUsers();
}

/**
 * "再来一局"菜单项的单击响应方法。
 */
void MainWindow::OnMenuItemRestartClicked() {
    mGame->Restart();
}

/**
 * 对手退出游戏事件的响应方法。
 * @param wParam    对手逃跑则为 TRUE，正常退出则为 FALSE
 * @param lParam    对手的名字
 * @return 总是零
 */
LRESULT MainWindow::OnRivalQuitGame(WPARAM wParam, LPARAM lParam) {
    // 设置菜单项
    CMenu* menu = CDialog::GetMenu();
    menu->EnableMenuItem(IDC_MENU_ITEM_FIND_RIVAL, MF_ENABLED);
    menu->EnableMenuItem(IDC_MENU_ITEM_DEFEAT, MF_GRAYED);
    menu->EnableMenuItem(IDC_MENU_ITEM_RESTART, MF_GRAYED);

    // 设置状态栏
    CString text;
    text.LoadString(IDS_CURRENT_RIVAL);
    mStatusBar.SetText(text, 0, 0);

    // 显示提示信息
    CString information((LPCTSTR)lParam);
    CString tempString;
    if (wParam) {
        tempString.LoadString(IDS_RIVAL_ESCAPE);
    } else {
        tempString.LoadString(IDS_RIVAL_QUIT);
    }
    information += tempString;
    AfxMessageBox(information, MB_ICONINFORMATION);

    return 0;
}
